#pragma once

#include "IntrusivePtr.h"
#include <boost/noncopyable.hpp>
#include <string>

namespace Sample
{
	class SampleClass : boost::noncopyable 
	{
	protected:
		volatile long _refCount;

	public:
		SampleClass(void);

		virtual void AddRef ();
		virtual void Release ();
		virtual void Print (const std::string& msg) const;

	};

	inline void intrusive_ptr_add_ref (SampleClass* ip) { ip->AddRef (); }
	inline void intrusive_ptr_release (SampleClass* ip) { ip->Release (); }

	ref class Client
	{
	private:
		boost::IntrusivePtr<SampleClass> _wrap;

	public:
		Client ()
		{
			_wrap = new SampleClass  ();
			_wrap->Print ("Client");

			byref (_wrap);
			byval (%_wrap);
			byimpl(_wrap);
			copy ();
			asNative();
		}
		~Client ()
		{
			_wrap.reset();
			System::GC::SuppressFinalize (this);
		}
		!Client ()
		{
			_wrap.reset();
		}

		void byref (boost::IntrusivePtr<SampleClass>% rv)
		{
			rv->Print ("byval");
		}

		void byval (boost::IntrusivePtr<SampleClass>^ rv)
		{
			rv->Print ("byref");
		}

		void byimpl (boost::IntrusivePtr<SampleClass> rv)
		{
			rv->Print ("byimpl");
		}

		void copy ()
		{
			boost::IntrusivePtr<SampleClass> cp (_wrap);
			cp->Print ("From copy");
		}

		void asNative ()
		{
			boost::intrusive_ptr<SampleClass> bptr (&*_wrap);
			boost::IntrusivePtr<SampleClass> p = bptr;

			bptr->Print ("from bptr");
			p->Print ("from p");
		}
	};
}

